/*
 *  main.cpp
 *  crawler
 *
 *  Created by Roy Zuo on 10-4-27.
 *  Copyright 2010 O2 Micro, Inc. All rights reserved.
 *
 */

#include "crawler.hpp"
#include <boost/program_options.hpp>
#include <iostream>
#include <fstream>

void perform_tasks ( boost::program_options::variables_map& vm )
{
	string server = vm["global.server"].as < string >();
	string port = vm["global.port"].as < string > ();
	string host = vm["global.host"].as < string > ();

	vector < string > paths = vm["arguments.path"].as < vector < string > > (); 
	
	HttpHeaderPairs headers;
	
	if ( vm.count ( "global.accept" ) )
	{
		headers["Accept"] = vm["global.accept"].as < string > ();
	}
	if ( vm.count ( "global.accept-charset" ) )
	{
		headers["Accept-Charset"] = vm["global.accept-charset"].as < string > ();
	}
	if ( vm.count ( "global.accept-encoding" ) )
	{
		headers["Accept-Encoding"] = vm["global.accept-encoding"].as < string > ();
	}
	if ( vm.count ( "global.accept-language" ) )
	{
		headers["Accept-Language"] = vm["global.accept-language"].as < string > ();
	}
	if ( vm.count ( "global.accept-ranges" ) )
	{
		headers["Accept-Ranges"] = vm["global.accept-ranges"].as < string > ();
	}
	if ( vm.count ( "global.cache-control" ) )
	{
		headers["Cache-Control"] = vm["global.cache-control"].as < string > ();
	}
	if ( vm.count ( "global.content-length" ) )
	{
		headers["Content-Length"] = vm["global.content-length"].as < string > ();
	}
	if ( vm.count ( "global.content-type" ) )
	{
		headers["Content-Type"] = vm["global.content-type"].as < string > ();
	}
	if ( vm.count ( "global.connection" ) )
	{
		headers["Connection"] = vm["global.connection"].as < string > ();
	}
	if ( vm.count ( "global.cookie" ) )
	{
		headers["Cookie"] = vm["global.cookie"].as < string > ();
	}
	if ( vm.count ( "global.date" ) )
	{
		headers["Date"] = vm["global.date"].as < string > ();
	}
	if ( vm.count ( "global.expect" ) )
	{
		headers["Expect"] = vm["global.expect"].as < string > ();
	}
	if ( vm.count ( "global.from" ) )
	{
		headers["From"] = vm["global.from"].as < string > ();
	}
	if ( vm.count ( "global.pragma" ) )
	{
		headers["Pragma"] = vm["global.pragma"].as < string > ();
	}
	if ( vm.count ( "global.proxy-authorization" ) )
	{
		headers["Proxy-Authorization"] = vm["global.proxy-authorization"].as < string > ();
	}
	if ( vm.count ( "global.range" ) )
	{
		headers["Range"] = vm["global.range"].as < string > ();
	}
	if ( vm.count ( "global.referer" ) )
	{
		headers["Referer"] = vm["global.referer"].as < string > ();
	}
	if ( vm.count ( "global.user-agent" ) )
	{
		headers["User-Agent"] = vm["global.user-agent"].as < string > ();
	}

	vector < string > proxies;
	if ( vm.count( "proxies.proxy" ) )
	{
		proxies = vm["proxies.proxy"].as < vector < string > > ();
	}

	vector < string > expressions;
	if ( vm.count( "expressions.expr" ) )
	{
		expressions = vm["expressions.expr"].as < vector < string > > ();
	}

	Crawler crawler ( string ( "http" ), host, paths, headers, proxies, expressions );
	crawler();
}

int main ( int argc, char* argv[] )
{
	boost::program_options::options_description od ( "Allowed options" );
	
	od.add_options () 
	( "help,h", "show command's usage." )
	( "server", boost::program_options::value < string > (), "" )
	( "port", boost::program_options::value <string> (), "" )
	( "host", boost::program_options::value < string > (), "" )
	( "path", boost::program_options::value < string > (), "" )
	( "accept", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "accept-charset", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "accept-encoding", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "accept-language", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "accept-ranges", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "cache-control", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "content-length", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "content-type", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "cookie", boost::program_options::value < string > (), "" )
	( "connection", boost::program_options::value < string > ()->default_value ( "close" ), "" )
	( "date", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "expect", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "from", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "pragma", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "proxy-authorization", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "range", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "referer", boost::program_options::value < string > ()->default_value ( "" ), "" )
	( "user-agent", boost::program_options::value < string > ()->default_value ( "Mozilla/5.0 (Linux; X11)" ), "" )
	( "proxies", boost::program_options::value < vector < string > > (), "" )
	( "expressions", boost::program_options::value < vector < string > > (), "" )
	( "config-file,c", boost::program_options::value < string > () -> default_value ( "crawler.config" ), "set a configuration file to transfer arguments." )
	;
	
	boost::program_options::variables_map vm;
	boost::program_options::store ( boost::program_options::parse_command_line  ( argc, argv, od ), vm );
	boost::program_options::notify ( vm );
	
	if ( vm.count ( "help" ) )
	{
		cout << od << "\n";
		goto cleanup;
	}
	else if ( vm.count ( "server" ) )
	{
		perform_tasks ( vm );
	}
	else if ( vm.count ( "config-file" ) )
	{
		string config_filename = vm["config-file"].as < string >();
		ifstream in ( config_filename.c_str() );
		if ( !in )
		{
			cout << "Cannot open configuration file." << endl;
			goto cleanup;
		}
		
		boost::program_options::options_description config_od ( "Allow configuration options" );
		config_od.add_options ()
		( "global.server", boost::program_options::value < string > (), "" )
		( "global.port", boost::program_options::value <string> (), "" )
		( "global.host", boost::program_options::value < string > (), "" )
		( "arguments.path", boost::program_options::value < vector < string > > (), "" )
		
		( "global.accept", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-charset", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-encoding", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-language", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-ranges", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.cache-control", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.content-length", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.content-type", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.cookie", boost::program_options::value < string > (), "" )
		( "global.connection", boost::program_options::value < string > ()->default_value ( "close" ), "" )
		( "global.date", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.expect", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.from", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.pragma", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.proxy-authorization", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.range", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.referer", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.user-agent", boost::program_options::value < string > ()->default_value ( "Mozilla/5.0 (Linux; X11)" ), "" )
		( "proxies.proxy", boost::program_options::value < vector < string > > (), "" )
		( "expressions.expr", boost::program_options::value < vector < string > > (), "" )
		;
		
		boost::program_options::variables_map config_vm;
		boost::program_options::store ( boost::program_options::parse_config_file ( in, config_od ), config_vm );
		boost::program_options::notify ( config_vm );
		
		perform_tasks ( config_vm );
	}
	else
	{
		string config_filename = "crawler.config";
		ifstream in ( config_filename.c_str() );
		if ( !in )
		{
			cout << "Cannot open configuration file." << endl;
			goto cleanup;
		}
		
		boost::program_options::options_description config_od ( "Allow configuration options" );
		config_od.add_options ()
		( "global.server", boost::program_options::value < string > (), "" )
		( "global.port", boost::program_options::value <string> (), "" )
		( "global.host", boost::program_options::value < string > (), "" )
		( "arguments.path", boost::program_options::value < vector < string > > (), "" )
		
		( "global.accept", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-charset", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-encoding", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-language", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.accept-ranges", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.cache-control", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.content-length", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.content-type", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.cookie", boost::program_options::value < string > (), "" )
		( "global.connection", boost::program_options::value < string > ()->default_value ( "close" ), "" )
		( "global.date", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.expect", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.from", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.pragma", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.proxy-authorization", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.range", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.referer", boost::program_options::value < string > ()->default_value ( "" ), "" )
		( "global.user-agent", boost::program_options::value < string > ()->default_value ( "Mozilla/5.0 (Linux; X11)" ), "" )
		( "proxies.proxy", boost::program_options::value < vector < string > > (), "" )
		( "expressions.expr", boost::program_options::value < vector < string > > (), "" )
		;
		
		boost::program_options::variables_map config_vm;
		boost::program_options::store ( boost::program_options::parse_config_file ( in, config_od ), config_vm );
		boost::program_options::notify ( config_vm );
		
		perform_tasks ( config_vm );
	}

	
cleanup:
	return 0;
}